package com.txzt.gaea.upgrade.project.service.impl;

import com.alibaba.fastjson.JSON;
import com.txzt.gaea.business.fund.domain.model.FundIssued;
import com.txzt.gaea.business.project.domain.model.ProjectFundExpenseRequest;
import com.txzt.gaea.business.project.domain.model.ProjectFundExpenseRequestDetail;
import com.txzt.gaea.business.project.service.IProjectFERService;
import com.txzt.gaea.business.util.TranslateUtil;
import com.txzt.gaea.common.base.service.impl.BaseServiceImpl;
import com.txzt.gaea.common.core.base.context.AdminUserContext;
import com.txzt.gaea.common.enums.*;
import com.txzt.gaea.common.exception.CustomException;
import com.txzt.gaea.flow.model.FlowBiz;
import com.txzt.gaea.flow.model.FlowBizStep;
import com.txzt.gaea.flow.service.FlowService;
import com.txzt.gaea.provide.model.FileInfo;
import com.txzt.gaea.provide.vo.FileInfoVo;
import com.txzt.gaea.upgrade.project.domain.model.*;
import com.txzt.gaea.upgrade.project.domain.vo.ProjectMainVo;
import com.txzt.gaea.upgrade.project.domain.vo.ProjectProgressVo;
import com.txzt.gaea.upgrade.project.service.IProjectMainService;
import com.txzt.gaea.vo.AdminUserVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jeecgframework.poi.word.WordExportUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@Service
public class ProjectMainServiceImpl extends BaseServiceImpl<ProjectMain> implements IProjectMainService {

    @Autowired
    private FlowService flowService;
    @Autowired
    private IProjectFERService projectFERService;

    /**
     * 开题拟制 - 编辑/提交
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int openDraftEdit(ProjectMain projectMain) {
        Long flowId = null;
        if (projectMain.getIsCheckSubmit()) {
            if (null == projectMain.getOpenDraftFlowId()) {
                //开启开题拟制审核流程
                flowId = flowService.startFlowUpgrade(projectMain.getId(), "tb_project_main","global_status",
                        GlobalStatus.OPEN_DRAFT_BACK.getCode(), GlobalStatus.OPEN_REVIEW_UNDO.getCode(),null,GlobalStatus.INIT.getCode(),
                        FlowFlagEnum.PROJECT_OPEN_DRAFT.getCode(), projectMain.getDeptId());
                projectMain.setFlowId(flowId);
                //开题拟制审核流程id
                projectMain.setOpenDraftFlowId(flowId);
            } else if (projectMain.getGlobalStatus().equals(GlobalStatus.OPEN_DRAFT_BACK.getCode())) {
                // 若项目状态为开题拟制 - 退回修改，需执行流程的退回修改的下一步操作
                flowService.nextStepOnlyForBack(projectMain.getOpenDraftFlowId());
            }
            //更新全局项目状态为开题拟制审核中
            projectMain.setGlobalStatus(GlobalStatus.OPEN_DRAFT_CHECK.getCode());
        }else {
            projectMain.setGlobalStatus(null);
        }
        //添加拟制经费预算明细
        projectMain.getExpenseList().forEach(expense -> {
            expense.setProjectId(projectMain.getId());
        });
        //添加拟制项目进度明细
        projectMain.getProgressList().forEach(progress -> {
            progress.setProjectId(projectMain.getId());
            progress.setProgressStatus(ProgressStatus.DOING.getCode());
        });
        //编辑项目经费信息（删除原始数据，重新插入新数据）
        sqlManager.lambdaQuery(ProjectExpense.class)
                .andEq(ProjectExpense::getProjectId,projectMain.getId())
                .select()
                .forEach(expense -> sqlManager.deleteById(ProjectExpense.class,expense.getId()));
        sqlManager.insertBatch(ProjectExpense.class,projectMain.getExpenseList());
        //编辑项目进度信息（删除原始数据，重新插入新数据）
        sqlManager.lambdaQuery(ProjectProgress.class)
                .andEq(ProjectProgress::getProjectId,projectMain.getId())
                .select()
                .forEach(expense -> sqlManager.deleteById(ProjectProgress.class,expense.getId()));
        sqlManager.insertBatch(ProjectProgress.class,projectMain.getProgressList());
        //更新项目信息
        return sqlManager.updateTemplateById(projectMain);
    }

    /**
     * 开题评审 - 编辑/提交
     *
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int openReviewEdit(ProjectMain projectMain) {
        Long flowId = null;
        if (projectMain.getIsCheckSubmit()) {
            if (null == projectMain.getOpenReviewFlowId()) {
                //开启项目开题评审审核流程
                flowId = flowService.startFlowUpgrade(projectMain.getId(), "tb_project_main","global_status",
                        GlobalStatus.OPEN_REVIEW_BACK.getCode(), GlobalStatus.OPEN_SUBMIT_UNDO.getCode(),null,GlobalStatus.OPEN_REVIEW_DONE.getCode(),
                        FlowFlagEnum.PROJECT_OPEN_REVIEW.getCode(), projectMain.getDeptId());
                projectMain.setFlowId(flowId);
                projectMain.setOpenReviewFlowId(flowId);
            } else if (projectMain.getGlobalStatus().equals(GlobalStatus.OPEN_REVIEW_BACK.getCode())) {
                // 若项目状态为开题评审 - 退回修改，需执行流程的退回修改的下一步操作
                flowService.nextStepOnlyForBack(projectMain.getOpenReviewFlowId());
            }
            projectMain.setOpenReviewBatch(System.currentTimeMillis());
            //更新全局状态为-开题评审-审核中
            projectMain.setGlobalStatus(GlobalStatus.OPEN_REVIEW_CHECK.getCode());
        }else {
            if (projectMain.getGlobalStatus() < GlobalStatus.OPEN_REVIEW_CHECK.getCode()) {
                //更新全局状态为-开题评审-资料已上传
                projectMain.setGlobalStatus(GlobalStatus.OPEN_REVIEW_DONE.getCode());
            }else {
                projectMain.setGlobalStatus(null);
            }
        }
        return sqlManager.updateTemplateById(projectMain);
    }


    /**
     * 开题评审 - 汇总提交
     * @param mainList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int openReviewCollect(List<ProjectMain> mainList) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        //新增项目经费申请
        Long ferId = getFerId(mainList);
        //获取评审批次
        AtomicInteger count = new AtomicInteger(0);
        mainList.forEach(main -> {
            ProjectMain target = new ProjectMain();
            if (null == main.getOpenReviewFlowId()){
                //开启项目评审审核流程
                Long flowId = flowService.startFlowUpgrade(main.getId(), "tb_project_main","global_status",
                        GlobalStatus.OPEN_REVIEW_BACK.getCode(), GlobalStatus.OPEN_SUBMIT_UNDO.getCode(),null,GlobalStatus.OPEN_REVIEW_DONE.getCode(),
                        FlowFlagEnum.PROJECT_OPEN_REVIEW.getCode(), main.getDeptId());
                target.setFlowId(flowId);
                target.setOpenReviewFlowId(flowId);
            }else {
                FlowBiz flowBiz = flowService.getFlowBiz(main.getOpenReviewFlowId());
                if (FlowBizStatusEnum.BACK.getCode().equals(flowBiz.getCurrentStatus())){
                    // 若项目状态为开题评审 - 退回修改，需执行流程的退回修改的下一步操作
                    flowService.nextStepOnlyForBack(main.getOpenReviewFlowId());
                }
            }
            target.setId(main.getId());
            //设置项目经费申请id
            target.setFerId(ferId);
            target.setMeetingPlan(main.getMeetingPlan());
            target.setExpertList(main.getExpertList());
            target.setReviewOpinion(main.getReviewOpinion());
            target.setOpenMaterial(main.getOpenMaterial());
            target.setOpenReviewOperator(adminUserVO.getId());
            target.setOpenReviewTime(new Date());
            //添加评审批次
            target.setOpenReviewBatch(System.currentTimeMillis());
            //更新全局状态为-开题评审-审核中
            target.setGlobalStatus(GlobalStatus.OPEN_REVIEW_CHECK.getCode());
            count.addAndGet(sqlManager.updateTemplateById(target));
            updateFile(main.getOpenOpinion(), main.getPlanNo(), 1);
            updateFile(main.getSignatureForm(), main.getPlanNo(), 1);
            updateFile(main.getOpinionForm(), main.getPlanNo(), 1);
            updateFile(main.getRelatedMaterial(), main.getPlanNo(), 1);
        });
        return count.get();
    }

    /**
     * 新增项目经费申请
     * @param mainList 项目信息
     * @return 项目经费申请id
     */
    private Long getFerId(List<ProjectMain> mainList) {
        ProjectFundExpenseRequest request = null;
        for (ProjectMain main: mainList){
            if (null != main.getFer()) {
                request = main.getFer();
                break;
            }
        }
        Long ferId = null;
        if (null != request) {
            //新增项目经费申请，返回项目经费申请id
            ferId = projectFERService.savePFERForProjectMain(request);
        }
        return ferId;
    }


    /**
     * 开题提报 - 编辑/提交
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int openSubmitEdit(ProjectMain projectMain) {
        Long flowId = null;
        if (projectMain.getIsCheckSubmit()) {
            if (null == projectMain.getOpenSubmitFlowId()) {
                //开启项目开题提报审核流程
                flowId = flowService.startFlowUpgrade(projectMain.getId(), "tb_project_main", "global_status",
                        GlobalStatus.OPEN_SUBMIT_BACK.getCode(), GlobalStatus.DOING.getCode(),null,GlobalStatus.OPEN_SUBMIT_DONE.getCode(),
                        FlowFlagEnum.PROJECT_OPEN_SUBMIT.getCode(), projectMain.getDeptId());
                projectMain.setFlowId(flowId);
                projectMain.setOpenSubmitFlowId(flowId);
            }else if (projectMain.getGlobalStatus().equals(GlobalStatus.OPEN_SUBMIT_BACK.getCode())) {
                // 若项目状态为开题提报 - 退回修改，需执行流程的退回修改的下一步操作
                flowService.nextStepOnlyForBack(projectMain.getOpenSubmitFlowId());
            }
            projectMain.setOpenSubmitBatch(System.currentTimeMillis());
            //更新全局状态为-开题提报-审核中
            projectMain.setGlobalStatus(GlobalStatus.OPEN_SUBMIT_CHECK.getCode());
        }else {
            if (projectMain.getGlobalStatus() < GlobalStatus.OPEN_SUBMIT_CHECK.getCode()) {
                //更新全局状态为-开题提报-资料已上传
                projectMain.setGlobalStatus(GlobalStatus.OPEN_SUBMIT_DONE.getCode());
            }else {
                projectMain.setGlobalStatus(null);
            }
        }
        return sqlManager.updateTemplateById(projectMain);
    }


    /**
     * 开题提报 - 汇总提交
     * @param mainList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int openSubmitCollect(List<ProjectMain> mainList) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        //新增项目经费申请
        Long ferId = getFerId(mainList);
        AtomicInteger count = new AtomicInteger(0);
        mainList.forEach(main -> {
            ProjectMain target = new ProjectMain();
            if (null == main.getOpenSubmitFlowId()){
                //开启项目提报审核流程
                Long flowId = flowService.startFlowUpgrade(main.getId(), "tb_project_main","global_status",
                        GlobalStatus.OPEN_SUBMIT_BACK.getCode(), GlobalStatus.DOING.getCode(),null,GlobalStatus.OPEN_SUBMIT_DONE.getCode(),
                        FlowFlagEnum.PROJECT_OPEN_SUBMIT.getCode(), main.getDeptId());
                target.setFlowId(flowId);
                target.setOpenSubmitFlowId(flowId);
            }else {
                FlowBiz flowBiz = flowService.getFlowBiz(main.getOpenSubmitFlowId());
                if (FlowBizStatusEnum.BACK.getCode().equals(flowBiz.getCurrentStatus())){
                    // 若项目状态为开题评审 - 退回修改，需执行流程的退回修改的下一步操作
                    flowService.nextStepOnlyForBack(main.getOpenSubmitFlowId());
                }
            }
            target.setId(main.getId());
            //设置项目经费申请id
            target.setFerId(ferId);
            target.setOpenOpinion(main.getOpenOpinion());
            target.setSignatureForm(main.getSignatureForm());
            target.setOpinionForm(main.getOpinionForm());
            target.setRelatedMaterial(main.getRelatedMaterial());
            target.setOpenSubmitOperator(adminUserVO.getId());
            target.setOpenSubmitTime(new Date());
            //添加提报批次
            target.setOpenSubmitBatch(System.currentTimeMillis());
            //更新全局状态为-开题提报-审核中
            target.setGlobalStatus(GlobalStatus.OPEN_SUBMIT_CHECK.getCode());
            count.addAndGet(sqlManager.updateTemplateById(target));
            updateFile(main.getOpenOpinion(), main.getPlanNo(), 1);
            updateFile(main.getSignatureForm(), main.getPlanNo(), 1);
            updateFile(main.getOpinionForm(), main.getPlanNo(), 1);
            updateFile(main.getRelatedMaterial(), main.getPlanNo(), 1);
        });
        return count.get();
    }

    private void updateFile(String newFileJson, String projectNo, Integer fileType){
        List<FileInfoVo> newList = new ArrayList<>();
        if (StringUtils.isNotEmpty(newFileJson)) {
            newList = JSON.parseArray(newFileJson, FileInfoVo.class);
        }
        //需新增的文件
        newList.forEach(item -> {
            FileInfo fileInfo = new FileInfo();
            fileInfo.setId(item.getFileId());
            FileInfo orgFile = this.sqlManager.single(FileInfo.class,fileInfo.getId());
            orgFile.setProjectNo(projectNo);
            orgFile.setBizType(fileType);
            orgFile.setId(null);
            this.sqlManager.insert(orgFile);
//            this.sqlManager.updateTemplateById(fileInfo);
        });
    }


    /**
     * 结题申请 - 编辑/提交
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int finishApplyEdit(ProjectMain projectMain){
        Long flowId = null;
        if (projectMain.getIsCheckSubmit()) {
//            //1、判定经费支出申请是否存在实际录入金额为0或为空
            Map<String,Object> params = new HashMap<>();
            params.put("projectId",projectMain.getId());
            List<ProjectFundExpenseRequestDetail> detailList = sqlManager.select("projectFundExpenseRequest.findFundByProject", ProjectFundExpenseRequestDetail.class, params);
            BigDecimal totalActualExpense = BigDecimal.ZERO;
            for (ProjectFundExpenseRequestDetail detail : detailList) {
                BigDecimal actualExpense = detail.getActualExpense();
                if (actualExpense != null) {
                    totalActualExpense = totalActualExpense.add(actualExpense);
                }
            }
            if (BigDecimal.ZERO.equals(totalActualExpense)){
                throw new CustomException("提交失败,使用经费不能为0");
            }
            // 2、判断经费是否下达
            FundIssued fundIssued = sqlManager.lambdaQuery(FundIssued.class)
                    .andEq(FundIssued::getProjectId,projectMain.getId())
                    .single();
            if (fundIssued ==null){
                throw new CustomException("提交失败, 经费未下达");
            }
            if (null == projectMain.getFinishApplyFlowId()) {
                //开启结题申请审核流程
                flowId = flowService.startFlowUpgrade(projectMain.getId(), "tb_project_main","global_status",
                        GlobalStatus.FINISH_APPLY_BACK.getCode(), GlobalStatus.FINISH_REVIEW_UNDO.getCode(),null,GlobalStatus.FINISH_APPLY_DONE.getCode(),
                        FlowFlagEnum.PROJECT_FINISH_APPLY.getCode(), projectMain.getDeptId());
                projectMain.setFlowId(flowId);
                //结题申请审核流程id
                projectMain.setFinishApplyFlowId(flowId);
            }else if (projectMain.getGlobalStatus().equals(GlobalStatus.FINISH_APPLY_BACK.getCode())) {
                // 若项目状态为结题申请 - 退回修改，需执行流程的退回修改的下一步操作
                flowService.nextStepOnlyForBack(projectMain.getFinishApplyFlowId());
            }
            //更新全局项目状态为结题申请审核中
            projectMain.setGlobalStatus(GlobalStatus.FINISH_APPLY_CHECK.getCode());
        }else {
            projectMain.setGlobalStatus(null);
        }
        return sqlManager.updateTemplateById(projectMain);
    }



    /**
     * 结题评审 - 编辑/提交
     *
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int finishReviewEdit(ProjectMain projectMain) {
        Long flowId = null;
        if (projectMain.getIsCheckSubmit()) {
            if (null == projectMain.getFinishReviewFlowId()) {
                //开启项目结题评审审核流程
                flowId = flowService.startFlowUpgrade(projectMain.getId(), "tb_project_main","global_status",
                        GlobalStatus.FINISH_REVIEW_BACK.getCode(), GlobalStatus.FINISH_SUBMIT_UNDO.getCode(),null,GlobalStatus.FINISH_REVIEW_DONE.getCode(),
                        FlowFlagEnum.PROJECT_FINISH_REVIEW.getCode(), projectMain.getDeptId());
                projectMain.setFlowId(flowId);
                projectMain.setFinishReviewFlowId(flowId);
            } else if (projectMain.getGlobalStatus().equals(GlobalStatus.FINISH_REVIEW_BACK.getCode())) {
                // 若项目状态为结题评审 - 退回修改，需执行流程的退回修改的下一步操作
                flowService.nextStepOnlyForBack(projectMain.getFinishReviewFlowId());
            }
            projectMain.setFinishReviewBatch(System.currentTimeMillis());
            //更新全局状态为-结题评审-审核中
            projectMain.setGlobalStatus(GlobalStatus.FINISH_REVIEW_CHECK.getCode());
        }else {
            if (projectMain.getGlobalStatus() < GlobalStatus.FINISH_REVIEW_CHECK.getCode()) {
                //更新全局状态为-结题评审-资料已上传
                projectMain.setGlobalStatus(GlobalStatus.FINISH_REVIEW_DONE.getCode());
            }else {
                projectMain.setGlobalStatus(null);
            }
        }
        return sqlManager.updateTemplateById(projectMain);
    }


    /**
     * 结题评审 - 汇总评审
     * @param mainList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int finishReviewCollect(List<ProjectMain> mainList) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        //新增项目经费申请
        Long ferId = getFerId(mainList);
        AtomicInteger count = new AtomicInteger(0);
        mainList.forEach(main -> {
            ProjectMain target = new ProjectMain();
            if (null == main.getFinishReviewFlowId()){
                //开启项目结题评审审核流程
                Long flowId = flowService.startFlowUpgrade(main.getId(), "tb_project_main","global_status",
                        GlobalStatus.FINISH_REVIEW_BACK.getCode(), GlobalStatus.FINISH_SUBMIT_UNDO.getCode(),null,GlobalStatus.FINISH_REVIEW_DONE.getCode(),
                        FlowFlagEnum.PROJECT_FINISH_REVIEW.getCode(), main.getDeptId());
                target.setFlowId(flowId);
                target.setFinishReviewFlowId(flowId);
            }else {
                FlowBiz flowBiz = flowService.getFlowBiz(main.getFinishReviewFlowId());
                if (FlowBizStatusEnum.BACK.getCode().equals(flowBiz.getCurrentStatus())){
                    // 若项目状态为开题评审 - 退回修改，需执行流程的退回修改的下一步操作
                    flowService.nextStepOnlyForBack(main.getFinishReviewFlowId());
                }
            }
            target.setId(main.getId());
            //设置项目经费申请id
            target.setFerId(ferId);
            target.setFinishReport(main.getFinishReport());
            target.setFinishReviewMeeting(main.getFinishReviewMeeting());
            target.setFinishExpertsList(main.getFinishExpertsList());
            target.setFinishReviewMaterial(main.getFinishReviewMaterial());
            target.setFinishReviewOpinion(main.getFinishReviewOpinion());
            target.setFinishReviewOperator(adminUserVO.getId());
            target.setFinishReviewTime(new Date());
            //添加评审批次
            target.setFinishReviewBatch(System.currentTimeMillis());
            //更新全局状态为-结题评审-审核中
            target.setGlobalStatus(GlobalStatus.FINISH_REVIEW_CHECK.getCode());
            count.addAndGet(sqlManager.updateTemplateById(target));
            updateFile(main.getOpenOpinion(), main.getPlanNo(), 9);
            updateFile(main.getSignatureForm(), main.getPlanNo(), 9);
            updateFile(main.getOpinionForm(), main.getPlanNo(), 9);
            updateFile(main.getRelatedMaterial(), main.getPlanNo(), 9);
        });
        return count.get();
    }


    /**
     * 结题呈报 - 编辑/提交
     *
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int finishSubmitEdit(ProjectMain projectMain) {
        Long flowId = null;
        if (projectMain.getIsCheckSubmit()) {
            if (null == projectMain.getFinishSubmitFlowId()) {
                //开启项目结题评审审核流程
                flowId = flowService.startFlowUpgrade(projectMain.getId(), "tb_project_main","global_status",
                        GlobalStatus.FINISH_SUBMIT_BACK.getCode(), GlobalStatus.FINISH.getCode(),null,GlobalStatus.FINISH_SUBMIT_DONE.getCode(),
                        FlowFlagEnum.PROJECT_FINISH_SUBMIT.getCode(), projectMain.getDeptId());
                projectMain.setFlowId(flowId);
                projectMain.setFinishSubmitFlowId(flowId);

            } else if (projectMain.getGlobalStatus().equals(GlobalStatus.FINISH_SUBMIT_BACK.getCode())) {
                // 若项目状态为结题评审 - 退回修改，需执行流程的退回修改的下一步操作
                flowService.nextStepOnlyForBack(projectMain.getFinishSubmitFlowId());
            }
            projectMain.setFinishSubmitBatch(System.currentTimeMillis());
            //更新全局状态为-结题评审-审核中
            projectMain.setGlobalStatus(GlobalStatus.FINISH_SUBMIT_CHECK.getCode());
        }else {
            if (projectMain.getGlobalStatus() < GlobalStatus.FINISH_SUBMIT_CHECK.getCode()) {
                //更新全局状态为-结题评审-资料已上传
                projectMain.setGlobalStatus(GlobalStatus.FINISH_SUBMIT_DONE.getCode());
            }else {
                projectMain.setGlobalStatus(null);
            }
        }
        return sqlManager.updateTemplateById(projectMain);
    }


    /**
     * 结题呈报 - 汇总呈报
     * @param mainList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int finishSubmitCollect(List<ProjectMain> mainList) {
        AdminUserVO adminUserVO = AdminUserContext.getUser();
        //新增项目经费申请
        Long ferId = getFerId(mainList);
        AtomicInteger count = new AtomicInteger(0);
        mainList.forEach(main -> {
            ProjectMain target = new ProjectMain();
            if (null == main.getFinishSubmitFlowId()){
                //开启项目结题评审审核流程
                Long flowId = flowService.startFlowUpgrade(main.getId(), "tb_project_main","global_status",
                        GlobalStatus.FINISH_SUBMIT_BACK.getCode(), GlobalStatus.FINISH.getCode(),null,GlobalStatus.FINISH_SUBMIT_DONE.getCode(),
                        FlowFlagEnum.PROJECT_FINISH_SUBMIT.getCode(), main.getDeptId());
                target.setFlowId(flowId);
                target.setFinishSubmitFlowId(flowId);
            }else {
                FlowBiz flowBiz = flowService.getFlowBiz(main.getFinishSubmitFlowId());
                if (FlowBizStatusEnum.BACK.getCode().equals(flowBiz.getCurrentStatus())){
                    // 若项目状态为开题评审 - 退回修改，需执行流程的退回修改的下一步操作
                    flowService.nextStepOnlyForBack(main.getFinishSubmitFlowId());
                }
            }
            target.setId(main.getId());
            //设置项目经费申请id
            target.setFerId(ferId);
            target.setFinishSubmitMeeting(main.getFinishSubmitMeeting());
            target.setFinishSubmitOpinion(main.getFinishSubmitOpinion());
            target.setFinishSignatureForm(main.getFinishSignatureForm());
            target.setFinishOpinionForm(main.getFinishOpinionForm());
            target.setFinishSubmitMaterial(main.getFinishSubmitMaterial());
            target.setFinishSubmitOperator(adminUserVO.getId());
            target.setFinishSubmitTime(new Date());
            //添加评审批次
            target.setFinishSubmitBatch(System.currentTimeMillis());
            //更新全局状态为-结题评审-审核中
            target.setGlobalStatus(GlobalStatus.FINISH_SUBMIT_CHECK.getCode());
            count.addAndGet(sqlManager.updateTemplateById(target));
            updateFile(main.getOpenOpinion(), main.getPlanNo(), 9);
            updateFile(main.getSignatureForm(), main.getPlanNo(), 9);
            updateFile(main.getOpinionForm(), main.getPlanNo(), 9);
            updateFile(main.getRelatedMaterial(), main.getPlanNo(), 9);
        });
        return count.get();
    }


    /**
     * 项目延期 - 提交
     *
     * @param projectDelay
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int projectDelay(ProjectDelay projectDelay) {
        if (null == projectDelay.getGlobalStatus()) {
            throw new CustomException("请求参数globalStatus缺失！");
        }
        if (GlobalStatus.DELAY_BACK.getCode().equals(projectDelay.getGlobalStatus())) {
            // 若项目状态为项目延期 - 退回修改，需执行流程的退回修改的下一步操作
            flowService.nextStepOnlyForBack(projectDelay.getFlowId());
            ProjectMain projectMain = new ProjectMain();
            projectMain.setId(projectDelay.getProjectId());
            projectMain.setGlobalStatus(GlobalStatus.DELAY_CHECK.getCode());
            return sqlManager.updateTemplateById(projectMain);
        }else {
            AdminUserVO adminUserVO = AdminUserContext.getUser();
            //开启项目延期审核流程
            Long flowId = flowService.startFlowUpgrade(projectDelay.getProjectId(), "tb_project_main", "global_status",
                    GlobalStatus.DELAY_BACK.getCode(), GlobalStatus.DELAY.getCode(), projectDelay.getGlobalStatus(), projectDelay.getGlobalStatus(),
                    FlowFlagEnum.PROJECT_DELAY_CHECK.getCode(), projectDelay.getDeptId());
            //新增项目延期审核记录
            projectDelay.setFlowId(flowId);
            projectDelay.setCreateBy(adminUserVO.getId());
            projectDelay.setCreateTime(new Date());
            sqlManager.insert(projectDelay, true);
            //新增项目延期相关信息
            ProjectMain projectMain = new ProjectMain();
            projectMain.setId(projectDelay.getProjectId());
            projectMain.setDelayId(projectDelay.getId());
            projectMain.setFlowId(flowId);
            projectMain.setGlobalStatus(GlobalStatus.DELAY_CHECK.getCode());
            return sqlManager.updateTemplateById(projectMain);
        }
    }


    /**
     * 项目终止 - 提交
     *
     * @param projectStop
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int projectStop(ProjectStop projectStop) {
        if (null == projectStop.getGlobalStatus()) {
            throw new CustomException("请求参数globalStatus缺失！");
        }
        if (GlobalStatus.STOP_BACK.getCode().equals(projectStop.getGlobalStatus())) {
            // 若项目状态为项目延期 - 退回修改，需执行流程的退回修改的下一步操作
            flowService.nextStepOnlyForBack(projectStop.getFlowId());
            ProjectMain projectMain = new ProjectMain();
            projectMain.setId(projectStop.getProjectId());
            projectMain.setGlobalStatus(GlobalStatus.STOP_CHECK.getCode());
            return sqlManager.updateTemplateById(projectMain);
        }else {
            AdminUserVO adminUserVO = AdminUserContext.getUser();
            //开启项目延期审核流程
            Long flowId = flowService.startFlowUpgrade(projectStop.getProjectId(), "tb_project_main", "global_status",
                    GlobalStatus.STOP_BACK.getCode(), GlobalStatus.STOP.getCode(), projectStop.getGlobalStatus(), projectStop.getGlobalStatus(),
                    FlowFlagEnum.PROJECT_STOP_CHECK.getCode(), projectStop.getDeptId());
            //新增项目延期审核记录
            projectStop.setFlowId(flowId);
            projectStop.setCreateBy(adminUserVO.getId());
            projectStop.setCreateTime(new Date());
            sqlManager.insert(projectStop, true);
            //新增项目延期相关信息
            ProjectMain projectMain = new ProjectMain();
            projectMain.setId(projectStop.getProjectId());
            projectMain.setStopId(projectStop.getId());
            projectMain.setFlowId(flowId);
            projectMain.setGlobalStatus(GlobalStatus.STOP_CHECK.getCode());
            return sqlManager.updateTemplateById(projectMain);
        }
    }

    @Override
    public List<ProjectDelay> getDelayByProjectId(Long projectId) {
        List<ProjectDelay> delayList = sqlManager.lambdaQuery(ProjectDelay.class)
                .andEq(ProjectDelay::getProjectId,projectId)
                .select();
        delayList.forEach(delay ->{
            delay.setCreateByName(TranslateUtil.getUserName(delay.getCreateBy()));
        });
        return delayList;
    }

    @Override
    public List<ProjectStop> getStopByProjectId(Long projectId) {
        List<ProjectStop> stopList = sqlManager.lambdaQuery(ProjectStop.class)
                .andEq(ProjectStop::getProjectId,projectId)
                .select();
        stopList.forEach(stop ->{
            stop.setCreateByName(TranslateUtil.getUserName(stop.getCreateBy()));
        });
        return stopList;
    }

    @Override
    public ProjectDelay queryByDelayId(Long delayId) {
        ProjectDelay projectDelay = sqlManager.single(ProjectDelay.class,delayId);
        projectDelay.setCreateByName(TranslateUtil.getUserName(projectDelay.getCreateBy()));
        projectDelay.setStepVoList(flowService.getFlowBizStep(projectDelay.getFlowId()));
        return projectDelay;
    }

    @Override
    public ProjectStop queryByStopId(Long stopId) {
        ProjectStop projectStop = sqlManager.single(ProjectStop.class,stopId);
        projectStop.setCreateByName(TranslateUtil.getUserName(projectStop.getCreateBy()));
        projectStop.setStepVoList(flowService.getFlowBizStep(projectStop.getFlowId()));
        return projectStop;
    }

    /**
     * 提交审核数据撤回
     * @param projectMain
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int revocationProjectMain(ProjectMain projectMain) {
        ProjectMain info = sqlManager.single(ProjectMain.class,projectMain.getId());
        //状态必须为  开题拟制/开题评审/开题提报/结题申请/结题评审/结题呈报/延期/终止   -   审核中
        if (!GlobalStatus.OPEN_DRAFT_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.OPEN_REVIEW_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.OPEN_SUBMIT_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.FINISH_APPLY_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.FINISH_REVIEW_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.FINISH_SUBMIT_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.DELAY_CHECK.getCode().equals(info.getGlobalStatus())
                && !GlobalStatus.STOP_CHECK.getCode().equals(info.getGlobalStatus())){
            throw new CustomException("数据不在审核中，不可撤回！");
        }
        List<FlowBizStep> stepList = sqlManager.query(FlowBizStep.class)
                .andEq("flow_biz_id",projectMain.getFlowId())
                .andEq("is_delete", IsDeleteEnum.NOTDELETE.getCode())
                .orderBy("step_no asc")
                .select();
        if (0 == stepList.size()) {
            throw new CustomException("撤回异常！");
        }else {
            //若当前流程第一步未审核，则可撤回
            if (null == stepList.get(0).getStepStatus()) {
                FlowBiz flowBiz = sqlManager.single(FlowBiz.class,projectMain.getFlowId());
                ProjectMain target = new ProjectMain();
                target.setId(info.getId());
                //状态退回至当前流程的退回修改状态值
                target.setGlobalStatus(flowBiz.getBizRevocationStatus());
                return sqlManager.updateTemplateById(target);
            }else {
                throw new CustomException("项目已开始审核，不可撤回！");
            }
        }
    }

    /**
     * 根据计划编号查询项目信息
     * @param planNo
     * @return
     */
    @Override
    public ProjectMain selectProjectByPlanNo(String planNo){
        return sqlManager.query(ProjectMain.class).andEq("plan_no",planNo)
                .andEq("is_delete",IsDeleteEnum.NOTDELETE.getCode()).single();
    }


    @Override
    public List<ProjectMainVo> getProjectFund(ProjectMainVo projectMainVo){
        if (CollectionUtils.isEmpty(projectMainVo.getIdList())) {
            projectMainVo.setIdList(null);
//            projectMainVo.getIdList().add(-1L);
        }
        List<ProjectMainVo> list = sqlManager.select("projectMain.selectProjectFund",ProjectMainVo.class,projectMainVo);
        if (CostType.INDIRECT.getCode().equals(projectMainVo.getCostType())) {
            list.forEach(main ->{
                ProjectExpense device = sqlManager.lambdaQuery(ProjectExpense.class)
                        .andEq(ProjectExpense::getProjectId,main.getId())
                        .andEq(ProjectExpense::getCostType,CostType.DEVICE.getCode())
                        .andEq(ProjectExpense::getAnnual,projectMainVo.getAnnual())
                        .single();

                ProjectExpense cooperation = sqlManager.lambdaQuery(ProjectExpense.class)
                        .andEq(ProjectExpense::getProjectId,main.getId())
                        .andEq(ProjectExpense::getCostType,CostType.COOPERATION.getCode())
                        .andEq(ProjectExpense::getAnnual,projectMainVo.getAnnual())
                        .single();
                if (null == device){
                    device = new ProjectExpense();
                    device.setExpenseYear(BigDecimal.ONE);
                }else if (null == device.getExpenseYear()){
                    device.setExpenseYear(BigDecimal.ONE);
                }
                if (null == cooperation){
                    cooperation = new ProjectExpense();
                    cooperation.setExpenseYear(BigDecimal.ONE);
                }else if (null == cooperation.getExpenseYear()){
                    cooperation.setExpenseYear(BigDecimal.ONE);
                }
                main.setDeviceCooperation(device.getExpenseYear().add(cooperation.getExpenseYear()));
//                main.setDeviceCooperation((null != device ? device.getExpenseYear() : BigDecimal.ONE).add((null != cooperation ? cooperation.getExpenseYear() : BigDecimal.ONE)));
            });
        }
        return list;
    }


    @Override
    public List<ProjectProgressVo> getProjectProgress(ProjectProgressVo projectProgressVo) {
        return sqlManager.select("projectMain.selectProjectProgress", ProjectProgressVo.class, projectProgressVo);
    }

    @Value("${template.delayTemplate}")
    private String delayTemplate;
    @Value("${template.stopTemplate}")
    private String stopTemplate;
    @Value("${template.finishTemplate}")
    private String finishTemplate;

    @Override
    public void exportWordProjectDelay(Long id, HttpServletResponse response) throws Exception{
        ProjectMain projectMain = sqlManager.single(ProjectMain.class, id);
        ProjectDelay projectDelay = sqlManager.single(ProjectDelay.class, projectMain.getDelayId());
        List<FlowBizStep> stepList = sqlManager
                .lambdaQuery(FlowBizStep.class)
                .andEq(FlowBizStep::getFlowBizId,projectDelay.getFlowId())
                .orderBy("step_no asc")
                .select();
        FlowBizStep headStep = null;
        FlowBizStep tailStep = null;
        if (!CollectionUtils.isEmpty(stepList)) {
            headStep = stepList.get(0);
            if (stepList.size() > 1) {
                tailStep = stepList.get(stepList.size() - 1);
            }
        }
        String pattern = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Map<String, Object> map = new HashMap<String, Object>(12);
        map.put("projectName",StringUtils.isNotEmpty(projectMain.getProjectName()) ? projectMain.getProjectName() : "");
        map.put("endYear", null != projectMain.getEndYear() ? projectMain.getEndYear() : "");
        map.put("estimatedFinishTime",null != projectDelay.getEstimatedFinishTime() ? simpleDateFormat.format(projectDelay.getEstimatedFinishTime()) : "");
        map.put("delayReason",StringUtils.isNotEmpty(projectDelay.getDelayReason()) ? projectDelay.getDelayReason() : "");
        map.put("projectLeaderOpinion",StringUtils.isNotEmpty(projectDelay.getProjectLeaderOpinion()) ? projectDelay.getProjectLeaderOpinion() : "");
        if (null != headStep) {
            map.put("headStepComment",StringUtils.isNotEmpty(headStep.getStepComment()) ? headStep.getStepComment() : "");
        }else {
            map.put("headStepComment","");
        }
        if (null != tailStep) {
            map.put("tailStepComment",StringUtils.isNotEmpty(tailStep.getStepComment()) ? tailStep.getStepComment() : "");
        }else {
            map.put("tailStepComment","");
        }
        map.put("remark",StringUtils.isNotEmpty(projectDelay.getRemark()) ? projectDelay.getRemark() : "");

        XWPFDocument doc = WordExportUtil.exportWord07(delayTemplate, map);
        //输出文件流
        OutputStream outputStream;
        outputStream = new BufferedOutputStream(response.getOutputStream());
        doc.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }


    @Override
    public void exportWordProjectStop(Long id, HttpServletResponse response) throws Exception {
        ProjectMain projectMain = sqlManager.single(ProjectMain.class, id);
        ProjectStop projectStop = sqlManager.single(ProjectStop.class, projectMain.getStopId());
        List<FlowBizStep> stepList = sqlManager
                .lambdaQuery(FlowBizStep.class)
                .andEq(FlowBizStep::getFlowBizId,projectStop.getFlowId())
                .orderBy("step_no asc")
                .select();
        FlowBizStep headStep = null;
        FlowBizStep tailStep = null;
        if (!CollectionUtils.isEmpty(stepList)) {
            headStep = stepList.get(0);
            if (stepList.size() > 1) {
                tailStep = stepList.get(stepList.size() - 1);
            }
        }
        Map<String, Object> map = new HashMap<String, Object>(12);
        map.put("projectName",StringUtils.isNotEmpty(projectMain.getProjectName()) ? projectMain.getProjectName() : "");
        map.put("endYear", null != projectMain.getEndYear() ? projectMain.getEndYear() : "");
        map.put("budgetFund", null != projectMain.getBudgetFund() ? projectMain.getBudgetFund() : "");
        map.put("stopReason",StringUtils.isNotEmpty(projectStop.getStopReason()) ? projectStop.getStopReason() : "");
        map.put("projectLeaderOpinion",StringUtils.isNotEmpty(projectStop.getProjectLeaderOpinion()) ? projectStop.getProjectLeaderOpinion() : "");
        if (null != headStep) {
            map.put("headStepComment",StringUtils.isNotEmpty(headStep.getStepComment()) ? headStep.getStepComment() : "");
        }else {
            map.put("headStepComment","");
        }
        if (null != tailStep) {
            map.put("tailStepComment",StringUtils.isNotEmpty(tailStep.getStepComment()) ? tailStep.getStepComment() : "");
        }else {
            map.put("tailStepComment","");
        }
        map.put("remark",StringUtils.isNotEmpty(projectStop.getRemark()) ? projectStop.getRemark() : "");

        XWPFDocument doc = WordExportUtil.exportWord07(stopTemplate, map);
        //输出文件流
        OutputStream outputStream;
        outputStream = new BufferedOutputStream(response.getOutputStream());
        doc.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    @Override
    public void exportWordProjectFinish(Long id, HttpServletResponse response) throws Exception {
        ProjectMain projectMain = sqlManager.single(ProjectMain.class, id);
        List<FlowBizStep> stepList = sqlManager
                .lambdaQuery(FlowBizStep.class)
                .andEq(FlowBizStep::getFlowBizId,projectMain.getFinishApplyFlowId())
                .orderBy("step_no asc")
                .select();
        FlowBizStep headStep = null;
        FlowBizStep tailStep = null;
        if (!CollectionUtils.isEmpty(stepList)) {
            headStep = stepList.get(0);
            if (stepList.size() > 1) {
                tailStep = stepList.get(stepList.size() - 1);
            }
        }
        String pattern = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Map<String, Object> map = new HashMap<String, Object>(12);
        map.put("projectName",StringUtils.isNotEmpty(projectMain.getProjectName()) ? projectMain.getProjectName() : "");
        map.put("endYear", null != projectMain.getEndYear() ? projectMain.getEndYear() : "");
        map.put("actualFinishTime", null != projectMain.getActualFinishTime() ? simpleDateFormat.format(projectMain.getActualFinishTime()) : "");
        map.put("budgetFund", null != projectMain.getBudgetFund() ? projectMain.getBudgetFund() : "");
        map.put("resultApplication",StringUtils.isNotEmpty(projectMain.getResultApplication()) ? projectMain.getResultApplication() : "");
        if (null != headStep) {
            map.put("headStepComment",StringUtils.isNotEmpty(headStep.getStepComment()) ? headStep.getStepComment() : "");
        }else {
            map.put("headStepComment","");
        }
        if (null != tailStep) {
            map.put("tailStepComment",StringUtils.isNotEmpty(tailStep.getStepComment()) ? tailStep.getStepComment() : "");
        }else {
            map.put("tailStepComment","");
        }
        map.put("remark",StringUtils.isNotEmpty(projectMain.getRemark()) ? projectMain.getRemark() : "");
        System.out.println(map);
        XWPFDocument doc = WordExportUtil.exportWord07(finishTemplate, map);
        //输出文件流
        OutputStream outputStream;
        outputStream = new BufferedOutputStream(response.getOutputStream());
        doc.write(outputStream);
        outputStream.flush();
        outputStream.close();
    }

    /**
     * 查询待审核数量(开题报告管理)
     * @param projectMain
     * @return
     */
    @Override
    public Long listCheckCount(ProjectMain projectMain) {
        List<Long> list = sqlManager.select("projectMain.selectProjectCheckCount", Long.class, projectMain);
        return list.get(0);
    }
}
